import asyncio
import time

from common.base.base_handler import BaseHandler
from services.automatic_control.model import AutomaticControl
from services.automatic_control.schemas.configs import PilotInformation
from settings import settings
from common.third_party.save_config import load_config, save_config, save_const, load_const


class AutomaticControlHandler(BaseHandler):
    __slots__ = ['model']

    async def handle_link_vswr_calibrate(self, params: dict) -> float | None:
        index = params['index']
        return await self.model.link_vswr_calibrate(index)

    async def handle_run_service_tx_ac(self):
        await self.model.run_service_tx_ac()

    async def handle_set_loops_states(self, params: dict) -> bool:
        link_tx_loop_state, link_rx_loop_state, service_tx_loop_state, service_rx_loop_state =\
            params['link_tx_loop_state'], params['link_rx_loop_state'], params['service_tx_loop_state'], params['service_rx_loop_state']

        save_config('ac/link_tx_loop_state', link_tx_loop_state)
        save_config('ac/link_rx_loop_state', link_rx_loop_state)
        save_config('ac/service_tx_loop_state', service_tx_loop_state)
        save_config('ac/service_rx_loop_state', service_rx_loop_state)

        need_service_tx_ac = service_tx_loop_state and not self.model.service_tx_loop_state

        self.model.link_tx_loop_state = link_tx_loop_state
        self.model.link_rx_loop_state = link_rx_loop_state
        self.model.service_tx_loop_state = service_tx_loop_state
        self.model.service_rx_loop_state = service_rx_loop_state

        return True

    async def handle_get_current_output_power(self, params: dict) -> float:
        index = params['index']
        return await self.model.get_current_output_power(index)

    async def handle_set_output_power_correct_number(self, params: dict):
        index, number = params['index'], params['number']
        self.model.set_output_power_correct_number(index, number)

    async def handle_set_additional_output_power_correct_number(self, params: dict):
        index, number = params['index'], params['number']
        self.model.set_additional_output_power_correct_number(index, number)

    async def handle_get_output_power_correct_number(self, params: dict):
        index = params['index']
        return self.model.output_power_correct_number[index]

    async def handle_get_additional_output_power_correct_number(self, params: dict):
        index = params['index']
        return self.model.additional_output_power_correct_number[index]

    async def handle_set_sm_base_power(self, params: dict):
        await self.model.set_sm_base_power(params['sm_base_power'])

    async def handle_set_rm_base_power(self, params: dict):
        await self.model.set_rm_base_power(params['rm_base_power'])

    async def handle_get_calibrate_history(self):
        return self.model.last_calibrate_history

    async def handle_stop_calibration(self):
        self.model.is_stop_calibration = True
        return True

    async def handle_set_loop_state(self, params: dict) -> bool:
        state = params['state']
        self.model.set_loop_state(state)
        return True

    async def handle_get_loop_state(self) -> bool:
        return self.model.loop_state

    async def handle_set_adjustment_state(self, params: dict) -> bool:
        state = params['state']
        await self.model.set_adjustment_state(state)
        return True

    async def handle_get_adjustment_state(self) -> bool:
        return self.model.adjustment_state

    async def handle_calibrate(self, params: dict) -> bool:
        sm_base_power, sm_cable_loss_dl, sm_state =\
            params['sm_base_power'], params['sm_cable_loss_dl'], params['sm_state']
        rm_output_power, rm_cable_loss, rm_state = \
            params['rm_output_power'], params['rm_cable_loss'], params['rm_state']
        acc_base_power_calibrate, acc_link_calibrate, acc_tx_service_calibrate = \
            params['acc_base_power_calibrate'], params['acc_link_calibrate'], params['acc_tx_service_calibrate']
        only_reach_the_power = params['only_reach_the_power']

        return await self.model.calibrate(
            sm_base_power, sm_cable_loss_dl, sm_state,
            rm_output_power, rm_cable_loss, rm_state,
            acc_base_power_calibrate, acc_link_calibrate, acc_tx_service_calibrate,
            only_reach_the_power
        )

    async def handle_get_actual_reference_freq_40mhz(self) -> float:
        ra_clocks_measured = self.model._carrier_frequency_ac.ra_clocks_measured
        if ra_clocks_measured is None:
            return 40_000_000.0

        return ra_clocks_measured

    async def handle_get_pilot_telemetry(self) -> PilotInformation:
        return self.model.pilot_telemetry

    async def handle_read_input_power(self, params: dict) -> float:
        index: int = params['index']
        return await self.model._read_input_power(index, True)

    async def handle_read_output_power(self, params: dict) -> float:
        index: int = params['index']
        return await self.model._read_output_power(index, True)

    async def handle_sync_ad(self, params: dict) -> float:
        index: int = params['index']
        return await self.model._sync_ad3(index)

    async def handle_read_pilot_power_rx(self, params: dict) -> float:
        index: int = params['index']
        return self.model._read_pilot_power(index)

    async def handle_read_pilot_power_rx_nl(self, params: dict) -> float:
        index: int = params['index']
        return self.model._read_pilot_power_nl(index)

    async def handle_read_pilot_power_pa_rx(self, params: dict) -> float:
        index: int = params['index']
        return self.model._read_pilot_power_pa(index)

    async def handle_read_pilot_power_pa_rx_nl(self, params: dict) -> float:
        index: int = params['index']
        return self.model._read_pilot_power_pa_nl(index)

    async def handle_read_pilot_power_rx_a(self, params: dict) -> float:
        index: int = params['index']
        return self.model._read_pilot_power_a(index)

    async def handle_read_pilot_power_rx_b(self, params: dict) -> float:
        index: int = params['index']
        return self.model._read_pilot_power_b(index)

    async def handle_read_pilot_power_rx_a_nl(self, params: dict) -> float:
        index: int = params['index']
        return self.model._read_pilot_power_a_nl(index)

    async def handle_read_pilot_power_rx_b_nl(self, params: dict) -> float:
        index: int = params['index']
        return self.model._read_pilot_power_b_nl(index)

    async def handle_read_pilot_threshold(self, params: dict) -> float:
        index: int = params['index']
        return self.model._read_pilot_threshold(index)

    async def handle_read_pilot_power_tx(self, params: dict) -> float:
        index: int = params['index']
        return self.model.read_pilot_state_dma_e5(index)[0]

    async def handle_enforce_sm_tx_ac(self, params: dict) -> bool:
        index, count = params['index'], params['count']

        if self.model._all_loop_state and self.model.service_tx_loop_state:
            for _ in range(count):
                await self.model._tx_services_control(only_one_index=index)
                await asyncio.sleep(1)

        return True

    async def handle_read_true_power(self, params: dict) -> float:
        index: int = params['index']
        return await self.model.read_true_power(index)

    async def handle_carrier_frequency_control_enable(self, params: dict):
        enable: bool = params['enable']
        self.model._carrier_frequency_control_enable = enable

    async def handle_read_status_of_link(self, params: dict) -> bool:
        index: int = params['index']
        return self.model._read_status_of_link(index)

    async def handle_calibration_in_progress(self) -> bool:
        return self.model.calibration_in_progress

    async def handle_calibration_in_progress_time(self) -> bool:
        if self.model.calibration_start_time is None:
            return False

        return time.monotonic() - self.model.calibration_start_time

    async def handle_carrier_frequency_control(self, params: dict) -> bool | None:
        freq: float = params['freq']
        await self.model._carrier_frequency_ac.carrier_frequency_control(freq, False)

    async def handle_get_force_find_pilot(self):
        return load_const('force_find_pilot', bool, False)

    async def handle_set_force_find_pilot(self, state: bool):
        save_const('force_find_pilot', state)

        return True

    def __init__(self) -> None:
        self.model = AutomaticControl()

        super(AutomaticControlHandler, self).__init__(request_queue_uuid=settings.AUTOMATIC_CONTROL_REQUEST_QUEUE)

        self.handle('run_service_tx_ac', self.handle_run_service_tx_ac)
        self.handle('link_vswr_calibrate', self.handle_link_vswr_calibrate)
        self.handle('set_loops_states', self.handle_set_loops_states)
        self.handle('set_sm_base_power', self.handle_set_sm_base_power)
        self.handle('set_rm_base_power', self.handle_set_rm_base_power)
        self.handle('set_loop_state', self.handle_set_loop_state)
        self.handle('get_loop_state', self.handle_get_loop_state)
        self.handle('set_adjustment_state', self.handle_set_adjustment_state)
        self.handle('get_adjustment_state', self.handle_get_adjustment_state)
        self.handle('calibrate', self.handle_calibrate)
        self.handle('get_actual_reference_freq_40mhz', self.handle_get_actual_reference_freq_40mhz)
        self.handle('get_pilot_telemetry', self.handle_get_pilot_telemetry)
        self.handle('set_output_power_correct_number', self.handle_set_output_power_correct_number)
        self.handle('get_current_output_power', self.handle_get_current_output_power)
        self.handle('get_calibrate_history', self.handle_get_calibrate_history)
        self.handle('stop_calibration', self.handle_stop_calibration)
        self.handle('read_input_power', self.handle_read_input_power)
        self.handle('read_output_power', self.handle_read_output_power)
        self.handle('read_status_of_link', self.handle_read_status_of_link)

        self.handle('read_pilot_power_rx', self.handle_read_pilot_power_rx)
        self.handle('read_pilot_power_rx_nl', self.handle_read_pilot_power_rx_nl)
        self.handle('read_pilot_power_pa_rx', self.handle_read_pilot_power_pa_rx)
        self.handle('read_pilot_power_pa_rx_nl', self.handle_read_pilot_power_pa_rx_nl)

        self.handle('read_pilot_power_rx_a', self.handle_read_pilot_power_rx_a)
        self.handle('read_pilot_power_rx_b', self.handle_read_pilot_power_rx_b)
        self.handle('read_pilot_power_rx_a_nl', self.handle_read_pilot_power_rx_a_nl)
        self.handle('read_pilot_power_rx_b_nl', self.handle_read_pilot_power_rx_b_nl)

        self.handle('read_pilot_threshold', self.handle_read_pilot_threshold)
        self.handle('sync_ad', self.handle_sync_ad)

        self.handle('read_pilot_power_tx', self.handle_read_pilot_power_tx)
        self.handle('enforce_sm_tx_ac', self.handle_enforce_sm_tx_ac)
        self.handle('read_true_power', self.handle_read_true_power)
        self.handle(
            'set_additional_output_power_correct_number',
            self.handle_set_additional_output_power_correct_number
        )

        self.handle('get_output_power_correct_number', self.handle_get_output_power_correct_number)
        self.handle(
            'get_additional_output_power_correct_number',
            self.handle_get_additional_output_power_correct_number
        )

        self.handle('carrier_frequency_control_enable', self.handle_carrier_frequency_control_enable)
        self.handle('calibration_in_progress', self.handle_calibration_in_progress)
        self.handle('calibration_in_progress_time', self.handle_calibration_in_progress_time)

        self.handle('carrier_frequency_control', self.handle_carrier_frequency_control)

        self.handle('get_force_find_pilot', self.handle_get_force_find_pilot)
        self.handle('set_force_find_pilot', self.handle_set_force_find_pilot)
